﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace LibraryGuard.Interfaces
{
	/// <summary>
	/// Single action information.
	/// </summary>
	/// <remarks>
	/// Every "edge action" should override ToString and return user-friendly description.
	/// </remarks>
	/// TODO: tests for short-lived objects needed
	public interface IActionInfo
	{
		/// <summary>
		/// Action id.
		/// </summary>
		object ActionId { get; }

		/// <summary>
		/// Indicates "edge action", i.e. action that executes last.
		/// </summary>
		bool IsEdgeAction { get; }

		/// <summary>
		/// Executes action.
		/// </summary>
		/// <param name="caller">ActionList that executed the command.</param>
		/// <returns></returns>
		bool Execute(IActionList actionList);
	}

	/// <summary>
	/// Action list.
	/// Each action is described by <see cref="IActionInfo.ActionId"/> and action type(class).
	/// Collection uses the above description to distinguish objects.
	/// Each object in the collection must be unique.
	/// </summary>
	public interface IActionList
		: IList<IActionInfo>, INotifyCollectionChanged
	{
		/// <summary>
		/// Adds action when collection doesn't contain it already(see interface summary).
		/// </summary>
		/// <param name="action"></param>
		/// <param name="id"></param>
		new bool Add(IActionInfo action);

		/// <summary>
		/// Adds action when collection doesn't contain it already(see interface summary).
		/// Ids are compared with custom Comparison.
		/// </summary>
		/// <param name="action"></param>
		/// <param name="id"></param>
		/// <param name="idComparer"></param>
		/// <returns></returns>
		bool Add(IActionInfo action, Comparison<object> idComparer);

		/// <summary>
		/// Replaces action info(if collection contains it already) or adds new object.
		/// </summary>
		/// <param name="action"></param>
		void Replace(IActionInfo action);

		/// <summary>
		/// Replaces action info(if collection contains it already) or adds new object.
		/// Ids are compared with custom Comparison
		/// </summary>
		/// <param name="action"></param>
		/// <param name="idComparer"></param>
		void Replace(IActionInfo action, Comparison<object> idComparer);

		/// <summary>
		/// Removes specified object using custom id comparer.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="id"></param>
		/// <param name="idComparer"></param>
		/// <returns></returns>
		bool Remove<T>(object id, Comparison<object> idComparer)
			where T : IActionInfo;

		/// <summary>
		/// Removes range of objects.
		/// </summary>
		/// <param name="start"></param>
		/// <param name="length"></param>
		void RemoveRange(int start, int count);
	}
}
